/**
@file
Contains Encode and Decode functions, and several structures
that wrap encoding information.

Version:
0.1.2

Last updated date:
2012-12-25
*/

#pragma once
#include <string>
#include <Windows.h>

namespace Zaf {
namespace __Internal {

//Internal use only.
inline void __Encode(int codePage, const std::wstring& in, std::string& out) {

	int requireSize = WideCharToMultiByte(
		codePage, 
		0,
		in.c_str(),
		in.length(),
		nullptr,
		0,
		nullptr,
		nullptr
	);

	if (requireSize == 0) {
		return;
	}

	out.resize(requireSize);

	int encodeLen = WideCharToMultiByte(
		codePage,
		0,
		in.c_str(),
		in.length(),
		&out[0],
		requireSize,
		nullptr,
		nullptr
	);
}

//Internal use only.
inline void __Decode(int codePage, const std::string& in, std::wstring& out) {

	int requireSize = MultiByteToWideChar(
		codePage,
		0,
		in.c_str(),
		in.length(),
		nullptr,
		0
	);

	if (requireSize == 0) {
		return;
	}

	out.resize(requireSize);

	int decodeLen = MultiByteToWideChar(
		codePage,
		0,
		in.c_str(),
		in.length(),
		&out[0],
		requireSize
	);
}
}



/**
Represents the active code page encoding in system.
*/
struct Ansi { static const int CodePage = CP_ACP; };

/**
Represents the UTF-8 encoding.
*/
struct Utf8 { static const int CodePage = CP_UTF8; };

/**
Converts a wide character string to multibyte character string,
using specified encoding.

@param in Wide character string to be converted.
@param out Multibyte character string, to preverse result.
*/
template<typename Encoding>
inline void Encode(const std::wstring& in, std::string& out) {
	__Internal::__Encode(Encoding::CodePage, in, out);
}

/**
This is an overload version of Encode, for convenient usage.

@param in Wide character string to be converted.
@return Multibyte character string.

@see Encode(const std::wstring&, std::string&)
*/
template<typename Encoding>
inline std::string Encode(const std::wstring& in) {
	std::string out;
	Encode<Encoding>(in, out);
	return out;
}

/**
Converts a multibyte character string to wide character string,
using specified encoding.

@param in Multibyte character string to be converted.
@param out Wide character string, to preserve result.
*/
template<typename Encoding>
inline void Decode(const std::string& in, std::wstring& out) {
	__Internal::__Decode(Encoding::CodePage, in, out);
}

/**
This is an overload version of Decode, for convenient usage.

@param in Multibyte character string to be converted.
@return Wide character string.

@see Decode(const std::string&, std::wstring&)
*/
template<typename Encoding>
inline std::wstring Decode(const std::string& in) {
	std::wstring out;
	Decode<Encoding>(in, out);
	return out;
}

};